import os
import re
import logging
import time
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, 
    QLineEdit, QPushButton, QListWidget, QCheckBox, QProgressBar, QTextEdit, 
    QFileDialog, QMessageBox, QComboBox, QListWidgetItem, QSlider
)
from PySide6.QtCore import Qt, QTimer

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    filename='batch_rename_qt.log'
)

class BatchImageRenamer(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("灵活图片重命名工具（PySide6 版）")
        self.resize(900, 700)

        # 初始化配置
        self.image_types = {
            "主图": {
                "prefix": "Main",
                "replace_chars": ["主", "图", "首"],
                "aliases": ["主图", "Main", "main", "主图文件夹"],
                "selected": False
            },
            "详情图": {
                "prefix": "Detail",
                "replace_chars": ["详情", "长图", "描述"],
                "aliases": ["详情图", "Detail", "detail", "详情文件夹"],
                "selected": False
            }
        }
        self.target_dir = ""  # 目标目录
        self.image_folders = []  # 存储 (文件夹路径, 类型)
        self.total_files = 0  # 总文件数
        self.processed_files = 0  # 已处理文件数
        self.delay = 0.1  # 操作延时

        # 创建 UI
        self.init_ui()

    def init_ui(self):
        # ========== 中心窗口与主布局 ==========
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)

        # ========== 1. 目录选择区 ==========
        dir_layout = QHBoxLayout()
        dir_label = QLabel("目标目录:")
        self.dir_edit = QLineEdit()
        self.dir_edit.setReadOnly(True)
        self.select_dir_btn = QPushButton("浏览...")
        self.select_dir_btn.clicked.connect(self.select_target_dir)

        dir_layout.addWidget(dir_label)
        dir_layout.addWidget(self.dir_edit)
        dir_layout.addWidget(self.select_dir_btn)
        main_layout.addLayout(dir_layout)

        # ========== 2. 图片类型选择区 ==========
        type_layout = QHBoxLayout()
        self.type_checkboxes = {}
        for type_name in self.image_types:
            cb = QCheckBox(type_name)
            cb.setChecked(self.image_types[type_name]["selected"])
            cb.stateChanged.connect(self.on_type_selected)
            self.type_checkboxes[type_name] = cb
            type_layout.addWidget(cb)
        main_layout.addLayout(type_layout)

        # ========== 3. 文件夹识别区 ==========
        folder_layout = QVBoxLayout()
        folder_label = QLabel("识别到的图片文件夹:")
        self.folder_list = QListWidget()
        self.refresh_folder_btn = QPushButton("刷新列表")
        self.refresh_folder_btn.clicked.connect(self.refresh_image_folders)

        folder_layout.addWidget(folder_label)
        folder_layout.addWidget(self.folder_list)
        folder_layout.addWidget(self.refresh_folder_btn)
        main_layout.addLayout(folder_layout)

        # ========== 4. 别名配置区 ==========
        alias_layout = QHBoxLayout()
        self.alias_combo = QComboBox()
        self.alias_combo.addItems(self.image_types.keys())
        self.alias_edit = QLineEdit()
        self.add_alias_btn = QPushButton("添加别名")
        self.add_alias_btn.clicked.connect(self.add_alias)

        alias_layout.addWidget(QLabel("为类型添加别名:"))
        alias_layout.addWidget(self.alias_combo)
        alias_layout.addWidget(self.alias_edit)
        alias_layout.addWidget(self.add_alias_btn)
        main_layout.addLayout(alias_layout)

        # ========== 5. 执行控制区 ==========
        action_layout = QHBoxLayout()
        self.start_btn = QPushButton("开始重命名")
        self.start_btn.clicked.connect(self.start_rename)
        self.delay_label = QLabel("操作延时(秒):")
        self.delay_slider = QSlider(Qt.Horizontal)
        self.delay_slider.setRange(0, 10)  # 0~1秒，步长0.1
        self.delay_slider.setValue(1)  # 默认0.1秒（对应值为1，实际 *0.1）
        self.delay_slider.valueChanged.connect(self.on_delay_changed)

        action_layout.addWidget(self.start_btn)
        action_layout.addWidget(self.delay_label)
        action_layout.addWidget(self.delay_slider)
        main_layout.addLayout(action_layout)

        # ========== 6. 进度与日志区 ==========
        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_label = QLabel("就绪")
        progress_layout = QHBoxLayout()
        progress_layout.addWidget(self.progress_label)
        progress_layout.addWidget(self.progress_bar)
        main_layout.addLayout(progress_layout)

        # 日志区
        log_label = QLabel("操作日志:")
        self.log_edit = QTextEdit()
        self.log_edit.setReadOnly(True)
        main_layout.addWidget(log_label)
        main_layout.addWidget(self.log_edit)

    # ========== 核心逻辑 ==========
    def select_target_dir(self):
        """选择目标目录"""
        dir_path = QFileDialog.getExistingDirectory(self, "选择目标目录")
        if dir_path:
            self.target_dir = dir_path
            self.dir_edit.setText(dir_path)
            self.log(f"已选择目标目录: {dir_path}")
            self.refresh_image_folders()

    def on_type_selected(self):
        """类型复选框变化时，刷新文件夹识别"""
        self.refresh_image_folders()

    def refresh_image_folders(self):
        """刷新识别到的图片文件夹"""
        self.folder_list.clear()
        self.image_folders = []

        if not self.target_dir:
            return

        # 收集选中的类型
        selected_types = [
            t for t in self.image_types 
            if self.type_checkboxes[t].isChecked()
        ]
        if not selected_types:
            self.log("请至少选择一种图片类型（主图/详情图）")
            return

        # 递归扫描文件夹
        def scan(current_dir):
            for item in os.listdir(current_dir):
                item_path = os.path.join(current_dir, item)
                if os.path.isdir(item_path):
                    # 检查是否匹配选中类型的别名
                    for type_name in selected_types:
                        if item in self.image_types[type_name]["aliases"]:
                            self.image_folders.append((item_path, type_name))
                            self.folder_list.addItem(f"[{type_name}] {item_path}")
                    # 递归扫描子文件夹
                    scan(item_path)

        scan(self.target_dir)
        self.log(f"已识别 {len(self.image_folders)} 个图片文件夹")

    def add_alias(self):
        """添加别名"""
        type_name = self.alias_combo.currentText()
        alias = self.alias_edit.text().strip()
        if not alias:
            QMessageBox.warning(self, "提示", "请输入别名")
            return

        if alias not in self.image_types[type_name]["aliases"]:
            self.image_types[type_name]["aliases"].append(alias)
            self.log(f"已为 [{type_name}] 添加别名：{alias}")
            self.alias_edit.clear()
            self.refresh_image_folders()  # 刷新识别

    def start_rename(self):
        """开始重命名"""
        # 获取选中的文件夹（默认全选）
        selected_items = self.folder_list.selectedItems()
        if not selected_items and self.image_folders:
            # 全选逻辑
            selected_folders = self.image_folders
        elif selected_items:
            selected_folders = [
                self.image_folders[i] 
                for i in range(self.folder_list.count()) 
                if self.folder_list.item(i).isSelected()
            ]
        else:
            QMessageBox.warning(self, "提示", "未选择图片文件夹")
            return

        # 统计总文件数
        self.total_files = 0
        for path, _ in selected_folders:
            self.total_files += len(self.get_image_files(path))

        if self.total_files == 0:
            QMessageBox.information(self, "提示", "选中的文件夹中无图片文件")
            return

        # 初始化进度
        self.processed_files = 0
        self.progress_bar.setValue(0)
        self.progress_label.setText(f"准备处理 {self.total_files} 个文件")
        self.start_btn.setEnabled(False)

        # 启动处理（用 QTimer 避免阻塞 UI）
        self.current_index = 0
        self.selected_folders = selected_folders
        self.timer = QTimer()
        self.timer.timeout.connect(self.process_next)
        self.timer.start(10)  # 小间隔启动，避免卡顿

    def process_next(self):
        """逐文件处理（避免阻塞 UI）"""
        if self.current_index >= len(self.selected_folders):
            self.timer.stop()
            self.log(f"处理完成！共处理 {self.processed_files}/{self.total_files} 个文件")
            self.progress_label.setText("处理完成")
            self.start_btn.setEnabled(True)
            return

        folder_path, type_name = self.selected_folders[self.current_index]
        type_config = self.image_types[type_name]
        prefix = type_config["prefix"]
        replace_chars = type_config["replace_chars"]

        # 获取图片文件并排序
        image_files = self.get_image_files(folder_path)
        sorted_files = self.sort_files_by_number(image_files)

        # 逐个重命名
        for idx, old_name in enumerate(sorted_files, start=1):
            try:
                old_path = os.path.join(folder_path, old_name)
                file_ext = os.path.splitext(old_name)[1].lower()
                new_name = f"{prefix}-{idx:03d}{file_ext}"
                new_path = os.path.join(folder_path, new_name)

                # 替换特殊字符
                for c in replace_chars:
                    new_name = new_name.replace(c, "-")

                os.rename(old_path, new_path)
                self.log(f"重命名：{old_name} → {new_name}")

                # 更新进度
                self.processed_files += 1
                progress = (self.processed_files / self.total_files) * 100
                self.progress_bar.setValue(int(progress))
                self.progress_label.setText(f"已处理 {self.processed_files}/{self.total_files} 个文件")

                # 延时
                time.sleep(self.delay)

            except Exception as e:
                self.log(f"重命名失败（{old_name}）：{str(e)}")

        self.current_index += 1

    def get_image_files(self, folder_path):
        """获取文件夹中的图片文件"""
        exts = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp']
        return [
            f for f in os.listdir(folder_path) 
            if os.path.isfile(os.path.join(folder_path, f)) 
            and os.path.splitext(f)[1].lower() in exts
        ]

    def sort_files_by_number(self, files):
        """按文件名中的数字排序"""
        def extract_num(filename):
            match = re.search(r'\d+', filename)
            return int(match.group()) if match else 0
        return sorted(files, key=extract_num)

    def on_delay_changed(self, value):
        """延时滑块变化（0~1秒，步长0.1）"""
        self.delay = value * 0.1  # slider值 0~10 → 0~1秒
        self.log(f"操作延时设置为: {self.delay} 秒")

    def log(self, msg):
        """输出日志到界面和文件"""
        timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
        log_msg = f"[{timestamp}] {msg}"
        self.log_edit.append(log_msg)
        logging.info(log_msg)

if __name__ == "__main__":
    app = QApplication([])
    window = BatchImageRenamer()
    window.show()
    app.exec()
